package backgroud;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Brook
 * 第一种：运行结果错误
 * 演示计数不准确，找出具体出错地问题
 */
public class MultiThreadsError implements Runnable{


    static MultiThreadsError instance = new MultiThreadsError();
    int index = 0;
    final boolean [] marked = new boolean[10000000];
    static AtomicInteger realIndex = new AtomicInteger();
    static AtomicInteger wrongCount = new AtomicInteger();
    static volatile CyclicBarrier cyclicBarrier1 = new CyclicBarrier(2);
    static volatile CyclicBarrier cyclicBarrier2 = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(instance);
        Thread thread2 = new Thread(instance);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(instance.index);
        System.out.println("真正运行次数："+realIndex.get());
        System.out.println("错误次数："+wrongCount.get());
    }

    @Override
    public void run() {
        /**
         * while (index < 10000) {
         *             index++;
         *         }
         */
        for (int i =0; i< 100000; i++) {
            marked[0] =true;
            try {
                //栅栏确保所有线程都执行完
                cyclicBarrier2.reset();
                cyclicBarrier1.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            index++;
            try {
                cyclicBarrier1.reset();
                cyclicBarrier2.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            realIndex.incrementAndGet();
            //synchronized拥有可见性，导致index判断失误
            synchronized (instance) {
                if (marked[index] && marked[index-1]) {
                    System.out.println("发生错误"+index);
                    wrongCount.incrementAndGet();
                }
                marked[index] = true;
            }

        }

    }
}
